---
author: Marcus Rohrmoser
categories:
- en
- development
date: "2010-01-27T18:42:00+00:00"
tags:
- cache
- Cocoa
- iPhone
- NSCachedURLResponse
- NSKeyedArchiver
- NSKeyedUnarchiver
- NSURLCache
- Objective C
title: NSCachedURLResponse / NSKeyedUnarchiver pain
type: post
url: /2010/01/nscachedurlresponse-nskeyedunarchiver-pain/
yourls_shorturl:
- http://s.mro.name/25
---
as the iPhone SDK comes with a rather dysfunctional [NSURLCache][1] — Apple suggests to implement it from scratch yourself in the [code examples about caching][2] — I went for just this.

Until I came across the [`[NSKeyedUnarchiver unarchiveObjectWithData:...]`](http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSKeyedUnarchiver_Class/Reference/Reference.html) not restoring `userInfo`, `storagePolicy` and `data` of [`NSCachedURLResponse`](http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSCachedURLResponse_Class/Reference/Reference.html).

Couldn't believe it and spent almost the whole day verifying that the error is not within my code but really the unarchiver treats those fields transient.

See yourself:

<pre class="line-numbers"><code class="language-objc">-(void)testiPhoneSDK312NSKeyedArchiver
{
//  prepare a NSCachedURLResponse
    NSCachedURLResponse *src = nil;
    {
        NSURL *i_url = [NSURL URLWithString:@"http://www.url.example/path/file.html"];
        NSString *i_mime = @"text/html";
        NSInteger expectedContentLength = 112;
        NSString *i_encoding = @"iso-8859-2";

        NSURLResponse *i_response = [[NSURLResponse alloc] initWithURL:i_url
            MIMEType:i_mime
            expectedContentLength:expectedContentLength
            textEncodingName:i_encoding];
        NSData *i_data = [@"Hello, world!" dataUsingEncoding:NSISOLatin2StringEncoding];
        NSURLCacheStoragePolicy i_storage =  NSURLCacheStorageAllowed;
        NSDictionary *i_userInfo = [NSDictionary dictionaryWithObject:
        [NSDate dateWithTimeIntervalSince1970:13] forKey:@"era"];

        NSCachedURLResponse *src = [[NSCachedURLResponse alloc] initWithResponse:i_response
            data:i_data
            userInfo:i_userInfo
            storagePolicy:i_storage];

//      ensure it's all in place:
        STAssertEqualObjects(i_url, src.response.URL, @"");
        STAssertEqualObjects(i_mime, src.response.MIMEType, @"");
        STAssertEquals((int)expectedContentLength, (int)src.response.expectedContentLength, @"");
        STAssertEqualObjects(@"file.html", src.response.suggestedFilename, @"");
        STAssertEqualObjects(i_encoding, src.response.textEncodingName, @"");

        STAssertEqualObjects(i_data, src.data, @"");
        STAssertEqualObjects(i_userInfo, src.userInfo, @"");
        STAssertEquals( 0u, src.storagePolicy, @"");
    }

//  archive + unarchive:
    NSCachedURLResponse *dst = [NSKeyedUnarchiver unarchiveObjectWithData:
      [NSKeyedArchiver archivedDataWithRootObject:src]];

//  check whether src == dst
    STAssertEqualObjects(src.response.URL, dst.response.URL, @"");
    STAssertEqualObjects(src.response.MIMEType, dst.response.MIMEType, @"");
    STAssertEquals(src.response.expectedContentLength, dst.response.expectedContentLength, @"");
    STAssertEqualObjects(src.response.suggestedFilename, dst.response.suggestedFilename, @"");
    STAssertEqualObjects(src.response.textEncodingName, dst.response.textEncodingName, @"");

//  !!!!!!!!!!
//  sad information loss after unarchiving:
    STAssertNil( dst.data, @"" );
    STAssertNil( dst.userInfo, @"" );
    STAssertEquals( 2u , dst.storagePolicy, @"" );
}

</code></pre>

When my NSURLCache replacement is ready I think about publishing it a github — interested anyone?

 [1]: http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSURLCache_Class/Reference/Reference.html
 [2]: http://developer.apple.com/iphone/library/samplecode/URLCache/index.html#//apple_ref/doc/uid/DTS40008061
